from machine import RTC, Pin, SPI
from ili9XXX import ili9XXX, st7789, DISPLAY_TYPE_ST7789, COLOR_MODE_BGR, PORTRAIT, MADCTL_MX, MADCTL_MV, MADCTL_MY
import os
import sdcard
import ntptime
import network
import time
import lvgl as lv
import espidf as esp
import neopixel
import config
import json

rtc = RTC()


# 定义RGB灯
class LED:
    led = neopixel.NeoPixel(pin=Pin(1), n=2, bpp=3)  # 创建控制对象
    throttle_ms = 400
    press_tick = 0

    def __init__(self):
        btn = Pin(16, Pin.IN, pull=Pin.PULL_DOWN)
        btn.irq(self.handle_switch, trigger=Pin.IRQ_FALLING)

    def set_rgb(self, rgb):
        if config.LED_STATUS:
            self.led.fill(rgb)
            self.led.write()
        config.LED_RGB = rgb
        config.save_conf()

    def reset(self):
        if config.LED_STATUS:
            self.led.fill(config.LED_RGB)
            self.led.write()
        else:
            self.close()

    def handle_switch(self, _):
        if time.ticks_diff(time.ticks_ms(), self.press_tick) > self.throttle_ms:
            self.press_tick = time.ticks_ms()
            config.LED_STATUS = not config.LED_STATUS
            self.switch(config.LED_STATUS)

    def switch(self, status):
        if status:
            self.open()
        else:
            self.close()

    def open(self):
        self.led.fill(config.LED_RGB)
        self.led.write()
        config.LED_STATUS = True
        config.save_conf()

    def close(self):
        self.led.fill([0, 0, 0])
        self.led.write()
        config.LED_STATUS = False
        config.save_conf()


led_controller = LED()


# 连接wifi
def connect_wifi(name, pwd):
    wlan = network.WLAN(network.STA_IF)  # STA模式
    wlan.active(True)  # 激活接口
    start_time = time.time()  # 记录时间做超时判断
    if not wlan.isconnected():
        print('connecting to network...')
        wlan.connect(name, pwd)  # 输入WIFI账号密码
        while not wlan.isconnected():
            if time.time() - start_time > 10:
                print('WIFI Connected Timeout!')
                wlan.active(False)
                return wlan
    if wlan.isconnected():
        print('connected!')
        config.IP = wlan.ifconfig()
        print('network information:', config.IP)
        return wlan


# 扫描wifi
def scan_wifi():
    try:
        wlan = network.WLAN(network.STA_IF)  # STA模式
        wlan.active(True)  # 激活接口
        wifi_list = wlan.scan()
        wifi_list = [[i[0].decode("utf-8"), i[3]] for i in wifi_list if i[0]]
        wifi_list.sort(key=lambda i: i[1], reverse=True)
        with open("/web/wifi_list.json", "w", encoding="utf-8") as fp:
            json.dump(wifi_list, fp)
        wlan.active(False)
        return wifi_list
    except Exception as err:
        print(err)


# 开启热点
def create_wifi(name, pwd):
    ap = network.WLAN(network.AP_IF)
    ap.active(True)
    ap.config(essid=name)
    if pwd is not None:
        ap.config(password=pwd)
    config.IP = ap.ifconfig()
    print('network information:', config.IP)
    return ap


# 同步时间
def sync_ntp():
    ntptime.NTP_DELTA = 3155644800  # 可选 UTC+8偏移时间（秒），不设置就是UTC0
    ntptime.host = 'ntp1.aliyun.com'  # 可选，ntp服务器，默认是"pool.ntp.org"
    try:
        ntptime.settime()  # 修改设备时间,到这就已经设置好了
    except Exception as error:
        print(error)


# 挂载SD卡
def mount_sdcard(root="/sd"):
    for i in range(2):
        try:
            spi = SPI(2, sck=Pin(5), mosi=Pin(6), miso=Pin(4))
            spi.init()
            tf = sdcard.SDCard(spi, Pin(7))
            os.mount(tf, root)
            print(os.listdir(root))
            break
        except Exception as err:
            print(err)
            time.sleep(0.1)


# 自定义st7789，实现镜像翻转
class ST7789_Mirror(ili9XXX):
    def __init__(self,
                 miso=-1, mosi=19, clk=18, cs=5, dc=16, rst=23, power=-1, backlight=4, backlight_on=1, power_on=0,
                 spihost=esp.HSPI_HOST, spimode=0, mhz=40, factor=4, hybrid=True, width=320, height=240, start_x=0,
                 start_y=0,
                 colormode=COLOR_MODE_BGR, rot=PORTRAIT, invert=True, double_buffer=True, half_duplex=True,
                 asynchronous=False, initialize=True, color_format=lv.COLOR_FORMAT.NATIVE_REVERSE):
        # Make sure Micropython was built such that color won't require processing before DMA

        if lv.color_t.__SIZE__ != 2:
            raise RuntimeError('st7789 micropython driver requires defining LV_COLOR_DEPTH=16')

        self.display_name = 'ST7789'

        self.init_cmds = [
            {'cmd': 0x11, 'data': bytes([0x0]), 'delay': 120},
            {'cmd': 0x13, 'data': bytes([0x0])},

            {'cmd': 0x36, 'data': bytes([
                self.madctl(colormode, rot,
                            (0x40, MADCTL_MX | MADCTL_MV, MADCTL_MY | MADCTL_MX, MADCTL_MY | MADCTL_MV))])},  # MADCTL

            {'cmd': 0xb6, 'data': bytes([0xa, 0x82])},
            {'cmd': 0x3a, 'data': bytes([0x55]), 'delay': 10},
            {'cmd': 0xb2, 'data': bytes([0xc, 0xc, 0x0, 0x33, 0x33])},
            {'cmd': 0xb7, 'data': bytes([0x35])},
            {'cmd': 0xbb, 'data': bytes([0x28])},
            {'cmd': 0xc0, 'data': bytes([0xc])},
            {'cmd': 0xc2, 'data': bytes([0x1, 0xff])},
            {'cmd': 0xc3, 'data': bytes([0x10])},
            {'cmd': 0xc4, 'data': bytes([0x20])},
            {'cmd': 0xc6, 'data': bytes([0xf])},
            {'cmd': 0xd0, 'data': bytes([0xa4, 0xa1])},
            {'cmd': 0xe0,
             'data': bytes([0xd0, 0x0, 0x2, 0x7, 0xa, 0x28, 0x32, 0x44, 0x42, 0x6, 0xe, 0x12, 0x14, 0x17])},
            {'cmd': 0xe1,
             'data': bytes([0xd0, 0x0, 0x2, 0x7, 0xa, 0x28, 0x31, 0x54, 0x47, 0xe, 0x1c, 0x17, 0x1b, 0x1e])},
            {'cmd': 0x21, 'data': bytes([0x0])},
            {'cmd': 0x2a, 'data': bytes([0x0, 0x0, 0x0, 0xe5])},
            {'cmd': 0x2b, 'data': bytes([0x0, 0x0, 0x1, 0x3f]), 'delay': 120},
            {'cmd': 0x29, 'data': bytes([0x0]), 'delay': 120}
        ]

        super().__init__(miso=miso, mosi=mosi, clk=clk, cs=cs, dc=dc, rst=rst, power=power, backlight=backlight,
                         backlight_on=backlight_on, power_on=power_on, spihost=spihost, spimode=spimode, mhz=mhz,
                         factor=factor, hybrid=hybrid,
                         width=width, height=height, start_x=start_x, start_y=start_y, invert=invert,
                         double_buffer=double_buffer,
                         half_duplex=half_duplex, display_type=DISPLAY_TYPE_ST7789, asynchronous=asynchronous,
                         initialize=initialize, color_format=color_format)


# 初始化屏幕
def init_display():
    if config.MIRROR_FLIP:
        disp = ST7789_Mirror(
            mosi=11, clk=12, cs=10, dc=21, rst=45, backlight=46, power=-1,
            width=240, height=240)
    else:
        disp = st7789(
            mosi=11, clk=12, cs=10, dc=21, rst=45, backlight=46, power=-1,
            width=240, height=240)
    dispp = lv.disp_get_default()
    theme = lv.theme_default_init(dispp, lv.palette_main(
        lv.PALETTE.BLUE), lv.palette_main(lv.PALETTE.RED), True, lv.font_default())
    dispp.set_theme(theme)
